package com.syqc.monitor.chart

import android.annotation.SuppressLint
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Path
import android.widget.TextView
import androidx.core.content.ContextCompat
import com.github.mikephil.charting.charts.Chart
import com.github.mikephil.charting.components.MarkerView
import com.github.mikephil.charting.data.Entry
import com.github.mikephil.charting.highlight.Highlight
import com.github.mikephil.charting.utils.MPPointF
import com.syqc.entity.HistoryLine
import com.syqc.monitor.R
import com.syqc.utils.Units

class SpeedChartMaker(
    context: Context?,
    private val list: List<HistoryLine.Location>
) : MarkerView(context, R.layout.custom_marker_speed) {
    private val tvTime: TextView = findViewById<TextView>(R.id.tvTime)
    private val tvSpeed: TextView = findViewById<TextView>(R.id.tvSpeed)
    private var index = 0
    private val time = context?.getString(R.string.desc_com_time_)
    private val speed = context?.getString(R.string.desc_com_speed)

    @SuppressLint("SetTextI18n")
    override fun refreshContent(e: Entry, highlight: Highlight) {
        index = e.x.toInt() //这个方法用于获得折线是哪根
        val detail = list[index]
        tvTime.text = "$time：${detail.time.substring(11)}"
        tvSpeed.text = "$speed：${detail.speed} ${Units.speed}"
        super.refreshContent(e, highlight)
    }

    override fun getOffsetForDrawingAtPoint(posX: Float, posY: Float): MPPointF {
        val offset: MPPointF = offset
        val chart: Chart<*> = chartView
        val width: Float = width.toFloat()
        val height = height.toFloat()
        // posY \posX 指的是markerView左上角点在图表上面的位置
        //处理Y方向
        if (posY <= height + ARROW_SIZE) { // 如果点y坐标小于markerView的高度，如果不处理会超出上边界，处理了之后这时候箭头是向上的，我们需要把图标下移一个箭头的大小
            offset.y = ARROW_SIZE.toFloat()
        } else { //否则属于正常情况，因为我们默认是箭头朝下，然后正常偏移就是，需要向上偏移markerView高度和arrow size，再加一个stroke的宽度，因为你需要看到对话框的上面的边框
            offset.y = -height - ARROW_SIZE - STOKE_WIDTH // 40 arrow height   5 stroke width
        }
        //处理X方向，分为3种情况，1、在图表左边 2、在图表中间 3、在图表右边
        if (posX > chart.width - width) { //如果超过右边界，则向左偏移markerView的宽度
            offset.x = -width
        } else { //默认情况，不偏移（因为是点是在左上角）
            offset.x = 0f
            if (posX > width / 2) { //如果大于markerView的一半，说明箭头在中间，所以向右偏移一半宽度
                offset.x = -(width / 2)
            }
        }
        return offset
    }

    override fun draw(canvas: Canvas, posX: Float, posY: Float) {
        val paint = Paint() //绘制边框的画笔
        paint.strokeWidth = STOKE_WIDTH
        paint.style = Paint.Style.STROKE
        paint.strokeJoin = Paint.Join.ROUND
        paint.color = ContextCompat.getColor(context, R.color.color_246)
        val whitePaint = Paint() //绘制底色白色的画笔
        whitePaint.style = Paint.Style.FILL
        whitePaint.color = Color.WHITE
        val chart: Chart<*> = chartView
        val width: Float = width.toFloat()
        val height = height.toFloat()
        val offset = getOffsetForDrawingAtPoint(posX, posY)
        val saveId: Int = canvas.save()
        val path: Path
        if (posY < height + ARROW_SIZE) { //处理超过上边界
            path = Path()
            path.moveTo(0f, 0f)
            if (posX > chart.width - width) { //超过右边界
                path.lineTo(width - ARROW_SIZE / 2, 0f)
                path.lineTo(width, -ARROW_SIZE + CIRCLE_OFFSET)
                path.lineTo(width, 0f)
            } else {
                if (posX > width / 2) { //在图表中间
                    path.lineTo(width / 2 - ARROW_SIZE / 4, 0f)
                    path.lineTo(width / 2, -ARROW_SIZE + CIRCLE_OFFSET)
                    path.lineTo(width / 2 + ARROW_SIZE / 4, 0f)
                } else { //超过左边界
                    path.lineTo(0f, -ARROW_SIZE + CIRCLE_OFFSET)
                    path.lineTo(0f + ARROW_SIZE / 2, 0f)
                }
            }
            path.lineTo(0f + width, 0f)
            path.lineTo(0f + width, 0f + height)
            path.lineTo(0f, 0f + height)
            path.lineTo(0f, 0f)
            path.offset(posX + offset.x, posY + offset.y)
        } else { //没有超过上边界
            path = Path()
            path.moveTo(0f, 0f)
            path.lineTo(0f + width, 0f)
            path.lineTo(0f + width, 0f + height)
            if (posX > chart.width - width) {
                path.lineTo(width, height + ARROW_SIZE - CIRCLE_OFFSET)
                path.lineTo(width - ARROW_SIZE / 2, 0f + height)
                path.lineTo(0f, 0f + height)
            } else {
                if (posX > width / 2) {
                    path.lineTo(width / 2 + ARROW_SIZE / 4, 0f + height)
                    path.lineTo(width / 2, height + ARROW_SIZE - CIRCLE_OFFSET)
                    path.lineTo(width / 2 - ARROW_SIZE / 4, 0f + height)
                    path.lineTo(0f, 0f + height)
                } else {
                    path.lineTo(0f + ARROW_SIZE / 2, 0f + height)
                    path.lineTo(0f, height + ARROW_SIZE - CIRCLE_OFFSET)
                    path.lineTo(0f, 0f + height)
                }
            }
            path.lineTo(0f, 0f)
            path.offset(posX + offset.x, posY + offset.y)
        }

        // translate to the correct position and draw
        canvas.drawPath(path, whitePaint)
        canvas.drawPath(path, paint)
        canvas.translate(posX + offset.x, posY + offset.y)
        draw(canvas)
        canvas.restoreToCount(saveId)
    }

    companion object {
        const val ARROW_SIZE = 40 // 箭头的大小
        private const val CIRCLE_OFFSET = 10f //因为我这里的折点是圆圈，所以要偏移，防止直接指向了圆心
        private const val STOKE_WIDTH = 2f //这里对于stroke_width的宽度也要做一定偏移
    }

}